//
// Created by luo on 2022-08-25.
//

#include "../opencv/OpenCv.h"

void QuickDemo::Test_basic()
{
    //创建Mat类
    cv::Mat a;  //声明一个矩阵头，矩阵头中的引用次数标记了矩阵数据的使用次数，类比智能指针
    a = cv::imread("C:\\Pictures\\data\\aero1.jpg"); //向a赋值，数据指针指向像素数据
    cv::Mat b = a; //复制矩阵头

    cv::Mat A = Mat_<double>(3,3);//创建一个3*3的矩阵，存放double数据

    //数据类型+通道数 区分灰度图与彩色图 CV_8UC3 八位无符号三通道
    cv::Mat x(640,480,CV_8UC3);
    cv::Mat y(3,3,CV_8UC1);

    //Mat类的构造
    //1.默认构造
    //2.如上述构造，尺寸+数据类型
    //3.利用Size()
    cv::Mat(Size(640,480),CV_8UC3);

    //4.利用已有的矩阵构造，但矩阵指针指向同一个地址
    cv::Mat m = x.clone();//复制一模一样的矩阵，彼此不关联

    //Mat类赋值
    //1.构造时赋值
    cv::Mat q(2,2,CV_8UC3,cv::Scalar(0,0,255));//三通道矩阵，每个像素都是0,0,255

    //2.枚举法赋值，数据流格式
    cv::Mat e = (cv::Mat_<int>(3,3)<<1,2,3,4,5,6,7,8,9); //输入个数一定要与矩阵元素个数相同
    cv::Mat r = (cv::Mat_<double>(2,3)<<1.0,2.1,3.2,4.0,5.1,6.2);
    cv::Mat l = (cv::Mat_<int>(3,3)<<1,2,3,4,5,6,7,8,9);
    cv::Mat s = (cv::Mat_<double>(2,3)<<1.0,2.1,3.2,4.0,5.1,6.2);
    cv::Mat u,k,f,o,w;

    //3.循环赋值法！！！***
    //赋值函数中声明的变量类型要与矩阵定义时变量类型相同
    cv::Mat t = cv::Mat_<int>(3,3);
    for(int i = 0; i<t.rows; i++) //矩阵行循环
    {
        for(int j = 0; j<t.cols; j++)//列
        {
            t.at<int>(i,j) = i+j;  //at方法访问像素
        }
    }

    //4.类方法赋值
    cv::Mat z = cv::Mat::eye(3,3,CV_8UC1); //单位矩阵
    cv::Mat n = (cv::Mat_<int>(1,3)<<1,2,3);
    cv::Mat v = cv::Mat::diag(n); //对角矩阵，参数必须是Mat的一维变量
    cv::Mat p = cv::Mat::ones(3,3,CV_8UC1);//全为1的矩阵
    cv::Mat h = cv::Mat::zeros(3,3,CV_8UC1);//全为0的矩阵

    //5.数组赋值

    //Mat类支持的运算,加减乘除，滤波，增强等操作
    //加减运算时必须保证两个矩阵数据类型相同
    u = e+l;
    k = r-s;
    f = 2*e;
    o = s/2.0;
    w = e-1;
//    double qw;
//    w = r*s; //矩阵数学乘积 cij = ai1b1j + ai2b2j +ai3b3j
//    qw = e.dot(l);//内积，double类型
//    o = a.mul(l);//矩阵对应位的乘积 cij = aijbij

    //Mat元素的读取
    //1.at方法读取Mat类矩阵的元素
    cv::Mat aa = (cv::Mat_<uchar>(3,3)<<1,2,3,4,5,6,7,8,9);
    int value = (int)aa.at<uchar>(0,0);
    //at后面要加上<type>模板
    //单通道图像是一个二维矩阵，多通道矩阵每个元素坐标都是多个数据

    //cv::Vec3b,cv::Vec3s,cv::Vec3i等等表示同一个元素的3个通道数据
    //b uchar , s short, w ushort, d double, f float, i int
    cv::Mat bb(3,4,CV_8UC3,cv::Scalar(0,0,1));
    cv::Vec3b vc3 = bb.at<cv::Vec3b>(0,0);
    int first,second,third;
    first = (int)vc3.val[0];
    second = (int)vc3.val[1];
    third = (int)vc3.val[2];

    //2.指针ptr读取Mat类矩阵的数据
    cv::Mat xx(3,4,CV_8UC3,cv::Scalar(0,0,1));
    for(int i = 0; i <xx.rows; i++)
    {
        uchar *ptr = xx.ptr<uchar>(i); // 大循环控制矩阵中的每一行，小括号声明了行数
        for(int j = 0; j<xx.cols*xx.channels(); j++) //控制矩阵中的每一行所有通道的数据
        {
            //每一行中存储的数据数量为列数与通道数的乘积，指针可以后移cols*channels()-1位
            std::cout<<(int)ptr[j]<<std::endl;
        }
        //若是确定需要访问的数据，可以直接给出行数和指针后移的位数
        //xx.ptr<uchar>(1)[2];//第2行第3个数据，下标都是从0开始
    }

    //3.通过迭代器访问Mat类矩阵的元素
    cv::Mat cc(3,3,CV_8UC3,Scalar(0,0,255));
    cv::MatIterator_<uchar>it = cc.begin<uchar>(); //起始
    cv::MatIterator_<uchar>it_end = cc.end<uchar>();//结束
    for(auto i = 0; it!=it_end; it++)
    {
        //先读取第一个元素的每一个通道，然后到第二个，直到最后一个
        cout<<(int)(*it)<<"";
        if((++i % cc.cols) == 0)
        {
            cout<<endl;
        }
    }

    //通过矩阵元素的地址定位方式访问元素
}
